/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.tchepannou.rails.core.api;

import com.tchepannou.rails.core.service.OptionService;
import com.tchepannou.util.MimeUtil;
import com.tchepannou.util.StringUtil;
import java.io.IOException;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Locale;
import org.apache.commons.lang.StringEscapeUtils;


/**
 * Utility functions to send to view
 * 
 * @author herve
 */
public class Util
{
    //-- Attributes
    private long _uid = System.currentTimeMillis ();
    private ContainerContext _context;


    //-- Public
    public void setContainerContext (ContainerContext context)
    {
        _context = context;
    }


    //-- OptionService method
    /**
     * Returns the value of a system option.
     * This method calls {@link OptionService#get(java.lang.String, java.lang.String)}
     *
     * @param name Name of the option
     * @param defaultValue default value to return if the option not set     
     */
    public String getOption (String name, String defaultValue)
    {
        OptionService srv = (OptionService)_context.findService (OptionService.class);
        return srv != null ? srv.get (name, defaultValue) : defaultValue;
    }

    /**
     * Returns the valud of the option {@link {OptionService#OPTION_SITE_URL}
     */
    public String getSiteUrl ()
    {
        return getOption (OptionService.OPTION_SITE_URL, "");
    }

    /**
     * Returns the value of the option {@link OptionService#OPTION_ASSET_URL}
     */
    public String getAssetUrl ()
    {
        return getOption (OptionService.OPTION_ASSET_URL, "");
//        boolean secure = false;
//        if (_context instanceof ActionContext)
//        {
//            ActionContext ac = (ActionContext)_context;
//            secure = ac.isSecure ();
//        }
//        return secure
//            ? getOption (OptionService.OPTION_ASSET_URL_HTTPS, "")
//            : getOption (OptionService.OPTION_ASSET_URL, "");
    }

    //-- String method
    public String repeat (String str, int count)
    {
        StringBuilder sb = new StringBuilder ();
        for (int i=0 ; i<count ; i++)
        {
            sb.append (str);
        }
        return sb.toString ();
    }

    
    //-- HTML methods
    public String encodeHtml (String str)
    {
        return encodeHtml (str, true);
    }

    public String encodeHtml (String str, boolean encodeCR)
    {
        try
        {
            StringWriter writer = new StringWriter ();
            StringEscapeUtils.escapeHtml (writer, str);
            String xstr = writer.toString ();
            if (!encodeCR)
            {
                xstr = xstr.replaceAll ("(?i)<br>", "\n");
                xstr = xstr.replaceAll ("(?i)<br/>", "\n");
            }
            return xstr;
        }
        catch (IOException e)
        {
            throw new RuntimeException ("Encoding error", e);
        }
    }

    public String encodeUrl (String str)
    {
        try
        {
            return str != null ? URLEncoder.encode (str, "utf-8") : null;
        }
        catch (UnsupportedEncodingException e)
        {
            return str;
        }
    }
    
    public String decodeHtml (String html)
    {
        return StringEscapeUtils.unescapeHtml (html);
    }

    public String encodeJavascript (String str)
    {
        return StringEscapeUtils.escapeJavaScript (str);
    }

    //-- XML methods
    public String encodeXml (String str)
    {
        return StringEscapeUtils.escapeXml (str);
    }

    //-- CSV method
    public String encodeCsv (String str)
    {
        return str != null ? StringEscapeUtils.escapeCsv (str) : StringUtil.EMPTY;
    }

    //-- Date methods
    public Date getNow ()
    {
        return new Date ();
    }

    public int getYear ()
    {
        return datePart (Calendar.YEAR);
    }

    public int getYear (Date d)
    {
        return datePart (Calendar.YEAR, d);
    }

    public int getMonth ()
    {
        return datePart (Calendar.MONTH);
    }

    public int getMonth (Date d)
    {
        return datePart (Calendar.MONTH, d);
    }

    public int getDay ()
    {
        return datePart (Calendar.DAY_OF_MONTH);
    }

    public int getDay (Date d)
    {
        return datePart (Calendar.DAY_OF_MONTH, d);
    }

    public int getMinute (Date d)
    {
        return datePart (Calendar.MINUTE, d);
    }

    public int getMinute ()
    {
        return datePart (Calendar.MINUTE);
    }

    public int getHour (Date d)
    {
        return datePart (Calendar.HOUR_OF_DAY, d);
    }

    public int getHour ()
    {
        return datePart (Calendar.HOUR_OF_DAY);
    }

    public int getSecond (Date d)
    {
        return datePart (Calendar.SECOND, d);
    }

    public int getSecond ()
    {
        return datePart (Calendar.SECOND);
    }

    private int datePart (int part)
    {
        Calendar cal = Calendar.getInstance ();
        return cal.get (part);
    }

    private int datePart (int part, Date date)
    {
        if (date == null)
        {
            return -1;
        }
        else
        {
            Calendar cal = new GregorianCalendar ();
            cal.setTime (date);
            return cal.get (part);
        }
    }

    //-- Misc
    public String getMimeType (String path)
    {
        return MimeUtil.getInstance().getMimeTypeByFile(path);
    }

    public long nextUID ()
    {
        return ++_uid;
    }


    //-- Localization method
    public List getLocales ()
    {
        List lst = Arrays.asList (Locale.getAvailableLocales ());
        Comparator c = new Comparator () {

            public int compare (Object o1, Object o2)
            {
                return o1.toString ().compareTo (o2.toString ());
            }
        };
        Collections.sort (lst, c);
        return lst;
    }


    //-- Collection methods
    public List shuffle (List lst)
    {
        Collections.shuffle (lst);
        return lst;
    }

    public List randomFilter (Collection lst, int max)
    {
        /* Random indexes */
        int xmax = Math.min (max, lst.size ());
        List<Integer> idx = new ArrayList<Integer> ();
        while (idx.size () < xmax)
        {
            double i = Math.random () * xmax;
            int ii = (int)i;
            if (!idx.contains (ii))
            {
                idx.add (ii);
            }
        }

        if (lst instanceof List)
        {
            return randomFilter((List)lst, idx);
        }
        else
        {
            List xlst = new ArrayList ();
            xlst.addAll (lst);
            return randomFilter(xlst, idx);
        }
    }

    private List randomFilter (List lst, List<Integer> idx)
    {
        List result = new ArrayList ();
        for (Integer i : idx)
        {
            result.add (lst.get (i));
        }
        return result;

    }
}
